package net.suncaper.hotel.common.framework;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * 前端控制器
 */
public class DispatcherServlet extends GenericServlet {
    private String basePackage;
    private Map<String, Method> methodMap = new HashMap<>();
    private Map<String, Object> controllerMap = new HashMap<>();

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        basePackage = config.getInitParameter("basePackage");
        scanControllers();
    }

    private void scanControllers() {
        try {
            Set<Class<?>> classes = ClassScanner.getClasses(basePackage);
            for (Class<?> clazz : classes) {
                if (clazz.isAnnotationPresent(RequestMapping.class)) {
                    RequestMapping classMapping = clazz.getAnnotation(RequestMapping.class);
                    String classPath = classMapping.value();
                    
                    Object controller = clazz.newInstance();
                    
                    Method[] methods = clazz.getDeclaredMethods();
                    for (Method method : methods) {
                        if (method.isAnnotationPresent(RequestMapping.class)) {
                            RequestMapping methodMapping = method.getAnnotation(RequestMapping.class);
                            String methodPath = methodMapping.value();
                            String fullPath = classPath + methodPath;
                            
                            methodMap.put(fullPath, method);
                            controllerMap.put(fullPath, controller);
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        
        String uri = request.getRequestURI();
        String contextPath = request.getContextPath();
        String path = uri.substring(contextPath.length());
        
        // 移除.do后缀
        if (path.endsWith(".do")) {
            path = path.substring(0, path.length() - 3);
        }
        
        // 处理通配符路由
        Method method = findMethod(path);
        Object controller = findController(path);
        
        if (method != null && controller != null) {
            try {
                method.invoke(controller, request, response);
            } catch (Exception e) {
                e.printStackTrace();
                response.sendError(500, "Internal Server Error");
            }
        } else {
            response.sendError(404, "Not Found");
        }
    }

    private Method findMethod(String path) {
        // 精确匹配
        if (methodMap.containsKey(path)) {
            return methodMap.get(path);
        }
        
        // 通配符匹配
        for (String pattern : methodMap.keySet()) {
            if (pattern.contains("*")) {
                String regex = pattern.replace("*", ".*");
                if (path.matches(regex)) {
                    return methodMap.get(pattern);
                }
            }
        }
        
        return null;
    }

    private Object findController(String path) {
        // 精确匹配
        if (controllerMap.containsKey(path)) {
            return controllerMap.get(path);
        }
        
        // 通配符匹配
        for (String pattern : controllerMap.keySet()) {
            if (pattern.contains("*")) {
                String regex = pattern.replace("*", ".*");
                if (path.matches(regex)) {
                    return controllerMap.get(pattern);
                }
            }
        }
        
        return null;
    }
}